package org.springblade.tms.module.gps.base;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.utils.EnumUtils;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.tms.global.enums.*;
import org.springblade.tms.module.exceptionreason.entity.TMExceptionReason;
import org.springblade.tms.module.exceptionreason.service.IExceptionReasonService;
import org.springblade.tms.module.exceptionrecord.entity.TMExceptionRecord;
import org.springblade.tms.module.exceptionrecord.service.IExceptionRecordService;
import org.springblade.tms.module.exceptiontype.entity.TMExceptionType;
import org.springblade.tms.module.exceptiontype.service.IExceptionTypeService;
import org.springblade.tms.module.gps.vo.GPSAlarmVO;
import org.springblade.tms.module.gps.vo.GPSFenceVO;
import org.springblade.tms.module.roadbook.entity.TMRoadBook;
import org.springblade.tms.module.roadbook.service.IRoadBookService;
import org.springblade.tms.module.sap.base.SapRequestService;
import org.springblade.tms.module.sap.dto.WaybillEventDTO;
import org.springblade.tms.module.transportlinepoint.entity.TMTransportLinePoint;
import org.springblade.tms.module.transportlinepoint.service.ITransportLinePointService;
import org.springblade.tms.module.transportorder.entity.TMTransportOrder;
import org.springblade.tms.module.transportorder.service.ITransportOrderService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

import static org.springblade.common.constant.TenantConstant.DEFAULT_TENANT_ID;

/**
 * @projectName: BladeX
 * @package: org.springblade.tms.module.gps.base
 * @className: GPSService
 * @author: yr
 * @description: gps服务
 * @date: 2022/5/6 14:01
 */
@Service
@AllArgsConstructor
@Slf4j
@Transactional
public class GPSService {

	private final ITransportLinePointService transportLinePointService;

	private final ITransportOrderService transportOrderService;

	private final SapRequestService sapRequestService;

	private final IExceptionReasonService exceptionReasonService;

	private final IExceptionTypeService exceptionTypeService;

	private final IExceptionRecordService exceptionRecordService;

	private final IRoadBookService roadBookService;

	/**
	 * @param gpsFenceVO:
	 * @return R<Boolean>
	 * @author yr
	 * @description 进出电子围栏服务
	 * @date 2022/5/6 14:17
	 */
	public R<Boolean> inAndOutOfTheElectronicFence(GPSFenceVO gpsFenceVO) {
		TMTransportOrder tmTransportOrder = transportOrderService.lambdaQuery().eq(TMTransportOrder::getTransportNo, gpsFenceVO.getConsigNo()).one();
		//判断是进还是出
		if (gpsFenceVO.getEventType().equals(FenceEventType.ENTER_THE_ELECTRONIC_FENCE.getValue())
			&& tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.ORDER_RECEIVED.getValue())) {
			List<TMTransportLinePoint> transportLinePoints = transportLinePointService.lambdaQuery().eq(TMTransportLinePoint::getFenceLat, gpsFenceVO.getFenceLat())
				.eq(TMTransportLinePoint::getFenceLon, gpsFenceVO.getFenceLon())
				.eq(TMTransportLinePoint::getParentId, gpsFenceVO.getConsigNo()).list();
			if (transportLinePoints.isEmpty()) {
				inFence(gpsFenceVO, tmTransportOrder, WaybillStatusEnum.LOADED, EventCodeEnum.ARRIVE_AT_THE_PICK_UP_POINT);
			} else {
				inFence(gpsFenceVO, tmTransportOrder, WaybillStatusEnum.ARRIVED, EventCodeEnum.DELIVERED);
			}
			return R.status(true);
		} else if ((gpsFenceVO.getEventType().equals(FenceEventType.DRIVE_OUT_OF_THE_ELECTRONIC_FENCE.getValue())
			&& (tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.ORDER_RECEIVED.getValue()) ||
			tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.LOADED.getValue())))) {
			if (tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFO4.getValue()) || tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFOA.getValue())
				|| tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFO5.getValue()) || tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFOB.getValue())) {
				inFence(gpsFenceVO, tmTransportOrder, WaybillStatusEnum.ARRIVE_AT_THE_TRANSFER_STATION, EventCodeEnum.DELIVERED);
			} else {
				inFence(gpsFenceVO, tmTransportOrder, WaybillStatusEnum.SHIPPED, EventCodeEnum.DELIVERED);
			}
			return R.status(true);
		}
		return R.status(true);
	}

	//进出电子围栏通用代码
	private void inFence(GPSFenceVO gpsFenceVO, TMTransportOrder tmTransportOrder, WaybillStatusEnum status, EventCodeEnum eventCode) {
		//记录日志
		TMTransportLinePoint tmTransportLinePoint = new TMTransportLinePoint();
		tmTransportLinePoint.setParentId(tmTransportOrder.getId());
		tmTransportLinePoint.setTransport(eventCode.getDescription());
		tmTransportLinePoint.setCreateTime(new Date());
		tmTransportLinePoint.setLocation(gpsFenceVO.getLon() + "," + gpsFenceVO.getLat());
		tmTransportLinePoint.setFenceLat(gpsFenceVO.getFenceLat());
		tmTransportLinePoint.setFenceLon(gpsFenceVO.getFenceLon());
		tmTransportLinePoint.setTenantId(DEFAULT_TENANT_ID);
		transportLinePointService.save(tmTransportLinePoint);
		//运单状态修改
		tmTransportOrder.setTransportStatus(status.getValue());
		transportOrderService.updateById(tmTransportOrder);
		//上报TM
		WaybillEventDTO waybillEventDTO = new WaybillEventDTO();
		BeanUtil.copyNonNull(tmTransportOrder, waybillEventDTO);
		waybillEventDTO.setType(SapTransportActionEnum.TRANSPORT.value());
		waybillEventDTO.setEventCode(eventCode.getValue());
		waybillEventDTO.setEventTime(LocalDateTime.now());
		waybillEventDTO.setTorId(tmTransportOrder.getOrderNo());
		sapRequestService.pushTmForUpdateWaybill(waybillEventDTO);
	}

	/**
	 * @param alarm:
	 * @return R<Boolean>
	 * @author yr
	 * @description gps预警推送服务
	 * @date 2022/5/6 17:16
	 */
	public R<Boolean> earlyWarningInformationPush(GPSAlarmVO alarm) {
		TMTransportOrder tmTransportOrder = transportOrderService.lambdaQuery().eq(TMTransportOrder::getTransportNo, alarm.getConsigNo()).one();
		TMExceptionRecord tmExceptionRecord = new TMExceptionRecord();
		tmExceptionRecord.setOrderType(OrderTypeEnum.SINGLE_TRANSPORT.getValue());
		tmExceptionRecord.setParentId(tmTransportOrder.getId());
		TMExceptionType exceptionType = exceptionTypeService.lambdaQuery().eq(TMExceptionType::getName, "GPS预警").one();
		tmExceptionRecord.setExceptionType(exceptionType.getId());
		TMExceptionReason tmExceptionReason = exceptionReasonService.lambdaQuery()
			.eq(TMExceptionReason::getParentId, exceptionType.getId())
			.eq(TMExceptionReason::getReasonDesc, EnumUtils.getEnumByValue(GpsAlarmTypeEnum.class, alarm.getAlarmType()).get().description()).one();
		tmExceptionRecord.setExceptionTypeDesc(tmExceptionReason.getId());
		tmExceptionRecord.setExceptionDate(alarm.getAlarmTime());
		tmExceptionRecord.setRemark(alarm.getAlarmMsg());
		tmExceptionRecord.setOrderStatus(tmTransportOrder.getTransportStatus());
		tmExceptionRecord.setTenantId(DEFAULT_TENANT_ID);
		exceptionRecordService.save(tmExceptionRecord);
		TMTransportLinePoint tmTransportLinePoint = new TMTransportLinePoint();
		tmTransportLinePoint.setParentId(tmTransportOrder.getId());
		tmTransportLinePoint.setLocation(alarm.getLon() + "," + alarm.getLat());
		tmTransportLinePoint.setTransport(tmExceptionReason.getReasonDesc() + (alarm.getAlarmStatus().equals(GpsAlarmStatusEnum.END.getValue()) ? GpsAlarmStatusEnum.END.getDescription() : GpsAlarmStatusEnum.START.getDescription()));
		tmTransportLinePoint.setTenantId(DEFAULT_TENANT_ID);
		transportLinePointService.save(tmTransportLinePoint);
		WaybillEventDTO waybillEventDTO = new WaybillEventDTO();
		BeanUtil.copyNonNull(tmExceptionRecord, waybillEventDTO);
		BeanUtil.copyNonNull(tmTransportOrder, waybillEventDTO);
		waybillEventDTO.setExceptionRemark(tmExceptionRecord.getRemark());
		TMExceptionType tmExceptionType = exceptionTypeService.getById(tmExceptionRecord.getExceptionType());
		waybillEventDTO.setExceptionType(tmExceptionType.getEventReasonCode());
		waybillEventDTO.setType(tmExceptionRecord.getOrderType());
		waybillEventDTO.setEventCode(EventCodeEnum.ExceptionReport.getValue());
		waybillEventDTO.setTorId(tmTransportOrder.getOrderNoNew());
		waybillEventDTO.setEventReasonCode(tmExceptionReason.getReasonCode());
		if (tmExceptionReason.getReasonDesc().equals(EnumUtils.getEnumByValue(GpsAlarmTypeEnum.class, "9").get().description())){
            sapRequestService.pushTmForUpdateWaybill(waybillEventDTO);
        }
		return R.status(true);
	}

	/**
	 * @param roadBook:
	 * @return void
	 * @author yr
	 * @description 电子路书接收
	 * @date 2022/7/5 10:25
	 */
	public void eRoadBook(TMRoadBook roadBook) {
		TMRoadBook tmRoadBook = roadBookService.lambdaQuery()
			.eq(TMRoadBook::getRoutePlanId, roadBook.getRoutePlanId())
			.one();
		if (roadBook.getType().equals("1")) {
			if (tmRoadBook != null) {
				roadBook.setId(tmRoadBook.getId());
			}
			roadBook.setTenantId(DEFAULT_TENANT_ID);
			roadBookService.saveOrUpdate(roadBook);
		} else {
			roadBookService.removeById(tmRoadBook);
		}
	}
}
